import Camera from "./Camera";
import Model from "./Model";
import colorShader from './shader/colorShader';
import lightShader from './shader/lightShader';


export default class Renderer {
    gl: WebGLRenderingContext;
    camera: Camera
    static _instance: Renderer = null;
    static get instance() {
        if (!this._instance) {
            this._instance = new Renderer();
        }
        return this._instance;
    }

    canvas = null;
    constructor() {
        this.canvas = document.getElementById("webglCanvas");
        let gl = this.canvas.getContext("webgl2");
        if (!gl) {
            console.error("您的浏览器不支持 WebGL2");
        }
        if (!gl) {
            gl = this.canvas.getContext("webgl");
        }
        if(!gl){
            console.error("您的浏览器不支持 WebGL");
        }
        this.gl = gl;
        // this.setCamera(camera);
    }
    setCamera(camera: Camera) {
        this.camera = camera;
    }
    // 创建和编译着色器函数
    createShader(type: GLenum, source: string) {
        let gl = this.gl;
        const shader = gl.createShader(type);
        gl.shaderSource(shader, source);
        gl.compileShader(shader);
        if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
            console.error("Shader compile error:", gl.getShaderInfoLog(shader));
        }
        return shader;
    }

    // 创建程序并链接函数
    createProgram([vertexShaderSource, fragmentShaderSource]: string[]) {
        let gl = this.gl;
        const program = gl.createProgram();
        const vertexShader = this.createShader(gl.VERTEX_SHADER, vertexShaderSource);
        const fragmentShader = this.createShader(gl.FRAGMENT_SHADER, fragmentShaderSource);
        gl.attachShader(program, vertexShader);
        gl.attachShader(program, fragmentShader);
        gl.linkProgram(program);
        if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
            console.error("Program link error:", gl.getProgramInfoLog(program));
        }
        gl.useProgram(program);
        return program;
    }
    shaderMaps = new Map();
    compliePrograms() {
        const colorShaderProgram = this.createProgram(colorShader);
        const lightShaderProgram = this.createProgram(lightShader);
        this.shaderMaps.set('colorShader', colorShaderProgram);
        this.shaderMaps.set('lightShader', lightShaderProgram);
    }
    getShader(name: string) {
        return this.shaderMaps.get(name);
    }
    render(models: Model[]) {
        let gl = this.gl;
        gl.clearColor(0.0, 0.0, 0.0, 1.0); // 设置背景颜色
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // 清空颜色和深度缓冲区
        let camera = this.camera;
        camera.updateViewMatrix();
        models.forEach(model => {
            // console.log(model.name)
            if (model instanceof Model && model.loaded /* && model.boundingSphere.isInView(camera)*/) {
                model.updateModelMatrix();
                let isLight = model.program === this.getShader('lightShader')
                // console.log('isLight',isLight)
                // 使用模型的着色器程序
                gl.useProgram(model.program);

                // 设置模型矩阵
                const modelMatrixLocation = gl.getUniformLocation(model.program, "modelMatrix");
                gl.uniformMatrix4fv(modelMatrixLocation, false, model.modelMatrix.matrix);

                // 设置视图矩阵
                const viewMatrixLocation = gl.getUniformLocation(model.program, "viewMatrix");
                gl.uniformMatrix4fv(viewMatrixLocation, false, camera.viewMatrix.matrix);

                // 设置投影矩阵
                const projectionMatrixLocation = gl.getUniformLocation(model.program, "projectionMatrix");
                gl.uniformMatrix4fv(projectionMatrixLocation, false, camera.setPerspectiveProjectionMatrix());
                // 绑定顶点数据和索引数据
                gl.bindBuffer(gl.ARRAY_BUFFER, model.buffers.vertexBuffer);
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.buffers.indexBuffer);

                const positionAttributeLocation = gl.getAttribLocation(model.program, "position");
                gl.enableVertexAttribArray(positionAttributeLocation);
                gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 7 * Float32Array.BYTES_PER_ELEMENT, 0);

                const colorAttributeLocation = gl.getAttribLocation(model.program, "color");
                gl.enableVertexAttribArray(colorAttributeLocation);
                gl.vertexAttribPointer(colorAttributeLocation,4,gl.FLOAT,false, 7 * Float32Array.BYTES_PER_ELEMENT,3 * Float32Array.BYTES_PER_ELEMENT);

                gl.bindBuffer(gl.ARRAY_BUFFER, model.buffers.normalBuffer);
                if (isLight) {
                    const normalAttributeLocation = gl.getAttribLocation(model.program, "normal");
                    gl.enableVertexAttribArray(normalAttributeLocation);
                    gl.vertexAttribPointer(normalAttributeLocation, 3, gl.FLOAT, true, 3 * Float32Array.BYTES_PER_ELEMENT, 0);
                    const lightPositionLocation = gl.getUniformLocation(model.program, "lightPosition");
                    gl.uniform3fv(lightPositionLocation, [4.0, 1.0, 6.0]); // 设置光源位置
                }
                // 绘制模型
                gl.drawElements(gl.TRIANGLES, model.buffers.indexCount, gl.UNSIGNED_SHORT, 0);
            }
        });
    }
}
window['renderer'] = Renderer.instance;